<?php
/**
 *
 * @author Jean-Nicolas DESJARDINS
 */
abstract class Jnd_Model_Abstract
{

	protected $id = 0;
	
    /**
     * @var Jnd_Model_Mapper_Abstract
     */
    protected $_mapper = null;

    public function __construct($options = null)
    {
        if (is_array($options)) {
            $this->setOptions($options);
        } elseif (intval($options) > 0) {
            $this->chercher(intval($options));
        }
    }

    public function initialise()
    {
        $dict = $this->_getMapper()->getDict();
        foreach ($dict as $key => $value) {
            $method = 'set' . ucfirst($key);
            $this->$method(null);
        }
    }

    /**
     * @return Jnd_Model_Mapper_Abstract
     */
    public function _getMapper()
    {
        if ($this->_mapper === null) {
            $mapperClass = str_replace('_Model_', '_Model_Mapper_',
                get_class($this)); //$parts = explode('_', $class);
            if (! class_exists($mapperClass)) {
                throw new Jnd_Exception("Mapper '$mapperClass' inexistante");
            }
            $this->_mapper = new $mapperClass();
        }
        return $this->_mapper;
    }

    abstract public function getId();

    abstract public function setId($id);

    /**
     * Fonction permettant de retourner les données du modèle (attributs sans '_') sous forme de tableau.
     * @return array()
     */
    public function toArray()
    {
        $listeAttributs = get_object_vars($this);
        foreach ($listeAttributs as $attribut => $value) {
            if ($attribut[0] == '_') {
                unset($listeAttributs[$attribut]);
            }
        }
        return $listeAttributs;
    }

    /**
     * Permet d'éviter de définir les accesseurs simples
     *
     * @param string $function
     * @param array $arguments
     * @throws Ddb_Exception
     */
    public function __call($function, $arguments)
    {
        $prefix = substr($function, 0, 3);
        if ($prefix == 'set') {
            $attrName = Jnd_Global_Methods::lcfirst(
                substr($function, 3));
            if (! property_exists($this, $attrName)) {
                throw new Jnd_Exception("Invalid property '$attrName'");
            }
            $this->$attrName = $arguments[0];
        } else if ($prefix == 'get') {
            $attrName = Jnd_Global_Methods::lcfirst(
                substr($function, 3));
            if (! property_exists($this, $attrName)) {
                throw new Jnd_Exception("Invalid property '$attrName'");
            }
            return $this->$attrName;
        } else {
            throw new Jnd_Exception("Méthode '$function' inexistante sur la classe '" . get_class(
                $this) . "'");
        }
    }

    public function __set($name, $value)
    {
        trigger_error("Utilisation dépréciée de __set", E_USER_WARNING);
        if (property_exists($this, $name)) {
            $this->$name = $value;
        } else {
            throw new Jnd_Exception("Invalid property '$name'");
        }
    }

    public function __get($name)
    {
        trigger_error("Utilisation dépréciée de __get", E_USER_WARNING);
        if (property_exists($this, $name)) {
            return $this->$name;
        }
        throw new Jnd_Exception("Invalid property '$name'");
    }

    public function __isset($name)
    {
        return property_exists($this, $name);
    }

    /**
     * Rempli l'objet avec les valeurs (totales ou partielles) fournies.
     * Appelle __call si la méthode n'existe pas ce qui peut renvoyer une exception.
     *
     * @param array $options
     * @return Jnd_Model_Abstract
     * @throws Jnd_Exception
     */
    public function setOptions(array $options)
    {
        foreach ($options as $key => $value) {
            $method = 'set' . ucfirst($key);
            $this->$method($value); //
        }
        return $this;
    }

    /**
     * Lancement de la fonction de sauvegarde du mapper
     * @return int
     */
    public function sauver()
    {
        $mapper = $this->_getMapper();
        return $mapper->sauver($this);
    }

    /**
     * Lancement de la fonction supprimer du mapper
     * @return int
     */
    public function supprimer($id)
    {
        $mapper = $this->_getMapper();
        return $mapper->supprimer($id);
    }

    /**
     * Rempli le modèle en cours avec les données
     * @param int $id
     * @return bool
     */
    public function charger($id)
    {
        $mapper = $this->_getMapper();
        return $mapper->chercher($id, $this);
    }

    /**
     * @deprecated Utiliser charger
     * @param int $id
     */
    public function chercher($id)
    {
        return $this->charger($id);
    }

    /**
     * Lister les éléments d'une table
     */
    public function lister($tri = null, $decalage = 0, $nombre = Jnd_Global_Constantes::PAGINATOR_TAILLE_DEFAUT)
    {
        $mapper = $this->_getMapper();
        return $mapper->lister($tri, $decalage, $nombre);
    }

    public function listerqq($decalage, $nombre, $ordre = null)
    {
        if (is_int($nombre) and is_int($decalage)) {
            $mapper = $this->_getMapper();
            $liste = $mapper->listerqq($decalage, $nombre, $this, $ordre);
            return $liste;
        } else {
            throw new Jnd_Exception("listerqq exige que le nombre ou le décalage soient des entiers");
        }
    }

    public function compter()
    {
        return $this->_getMapper()->compter();
    }

    /**
     * Fonction permettant de générer une Zend_Db_Table_Select pour le Datagrid
     *
     * @param array $values
     * @param unknown_type $environnement
     * @param string $identite
     * @param array $options
     */
    public function getListSelect($values, $environnement, $identite, $options = null)
    {
        $mapper = $this->_getMapper();
        return $mapper->getListSelect($values, $environnement, $identite, $options);
    }
    
    public function listerPourSelect($blank = true, $value = "nom", $cle = "id") {
        $liste = $this->lister($value);
        $result = array();
        if ($blank) {
            $result[''] = __("");
        }
        foreach( $liste as $utilisateur) {
            $methodeCle = "get" . ucfirst($cle);
            $methodeValue = "get" . ucfirst($value);
            $result[$utilisateur->$methodeCle()] = $utilisateur->$methodeValue();
        }
        return $result;
    }
    
}
